package ongd.negocio.gestion;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import ongd.negocio.sesion.ControladorSesion;
import ongd.servicios.persistencia.ControladorPersistencia;
import ongd.servicios.persistencia.exceptions.IllegalOrphanException;
import ongd.servicios.persistencia.exceptions.NonexistentEntityException;
import ongd.servicios.persistencia.exceptions.PreexistingEntityException;

/**
 * Clase que realizará las operaciones necesarias para gestionar
 * los usuarios.
 *
 * @author <a href="mailto:egi0002@alu.ubu.es">Elena García Iglesias</a>
 * @author <a href="mailto:cms0021@alu.ubu.es">Cristina Martínez Sanz</a>
 * @version 1.0 20120124
 */
public class ControladorUsuario {

    /**
     * Objeto del tipo controlador persistencia que nos servirá para crear 
     * las instancias de las diferentes entidades.
     */
    private ControladorPersistencia contP;
    /**
     * Objeto del tipo controlador sesion que nos servirá para sabre 
     * en que sesion estamos.
     */
    private ControladorSesion contSesion;

    /**
     * Constructor de la clase.
     * @param contP controlador de persistencia.
     * @param contSesion controlador de sesion. 
     */
    public ControladorUsuario(ControladorPersistencia contP, ControladorSesion contSesion) {
        this.contP = contP;
        this.contSesion = contSesion;
    }

    /**
     * Método que crea un usuario.
     * @param usuario que vamos a crear.
     * @return ture si se ha creado correctamente o false si no ha sido así.
     * @throws PreexistingEntityException
     * @throws Exception 
     */
    public boolean crearUsuario(Usuario usuario) throws PreexistingEntityException, Exception {
        //Miramos que no existe el usuario
        if (contP.obtenerEntidad(Usuario.class, usuario.getIdusuario()) == null) {
            if (usuario.getIdusuario() != null && usuario.getNombre() != null && usuario.getApellidos() != null && usuario.getPassword() != null) {
                if (!usuario.getAvisos() || (usuario.getAvisos() && usuario.getEmail() != null)) {
                    usuario.setActivo(true);
                    contP.crearEntidad(usuario);
                    //Crearemos una alerta para avisar al usuario creado.
                    String mensaje = "Ha sido dado de alta como usuario en AplicacionONGD.\n Su idUsuario es:" + usuario.getIdusuario()
                            + " y la contraseña es: " + usuario.getPassword() + ".";
                    List<String> direccion = new ArrayList<String>();
                    direccion.add(usuario.getEmail());
                    contSesion.getControladorConfiguracion().enviarAlerta(direccion, "Alta de Usuario", mensaje);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Método que edita un usuario.
     * @param usuario que vamos a editar.
     * @return true si se ha editado correctamente o false si no ha sido así.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException
     * @throws Exception 
     */
    public boolean editarUsuario(Usuario usuario) throws IllegalOrphanException, NonexistentEntityException, Exception {
        if (contP.obtenerEntidad(Usuario.class, usuario.getIdusuario()) != null) {
            if (usuario.getIdusuario() != null && usuario.getNombre() != null && usuario.getApellidos() != null && usuario.getPassword() != null) {
                if (!usuario.getAvisos() || (usuario.getAvisos() && usuario.getEmail() != null)) {
                    contP.editarEntidad(usuario);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Método que borra un usuario de la base de datos.
     * @param usuario que vamosa  borrar.
     * @return true si se ha borrado correctamente o false si el usuario no existe.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException 
     */
    public boolean borrarUsuario(Usuario usuario) throws IllegalOrphanException, NonexistentEntityException {
        if (contP.obtenerEntidad(Usuario.class, usuario.getIdusuario()) != null) {
            contP.destroyEntidad(Usuario.class, usuario.getIdusuario());
            return true;
        }
        return false;
    }

    /**
     * Método que desactiva un usuario.
     * @param usuario que queremos desactivar.
     * @return true si se ha realizado la modificación correctamente o false si no ha sido así.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException
     * @throws Exception 
     */
    public boolean desactivarUsuario(Usuario usuario) throws IllegalOrphanException, NonexistentEntityException, Exception {
        if (usuario.getActivo()) {
            usuario.setActivo(false);
            return editarUsuario(usuario);
        }
        return false;
    }

    /**
     * Método que activa un usuario.
     * @param usuario que queremos activar.
     * @return true si se ha activado correctamente o false si no ha sido así.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException
     * @throws Exception 
     */
    public boolean activarUsuario(Usuario usuario) throws IllegalOrphanException, NonexistentEntityException, Exception {
        if (!usuario.getActivo()) {
            usuario.setActivo(true);
            return editarUsuario(usuario);
        }
        return false;
    }

    /**
     * Método que comprueba que existe un usuario activo con un determinado identificador y contraseña.
     * @param idUsuario identificador del usuario.
     * @param password contraseña.
     * @return true si existe un usuario con esos datos o false si no es así.
     */
    public boolean comprobarUsuario(String idUsuario, String password) {
        for (Usuario usuario : obtenerUsuariosActivos()) {
            if (usuario.getIdusuario().compareTo(idUsuario) == 0 && usuario.getPassword().compareTo(password) == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * Método que envia un email a un usuario con sus datos de acceso a la validación. 
     * @param idUsuario ideantifiacdor del suario.
     * @return true si se ha enviado o false.
     */
    public boolean enviarEmailUsuario(String idUsuario) {
        //Buscamos el usuario en la base de datos
        for (Usuario usuario : obtenerUsuariosActivos()) {
            if (usuario.getIdusuario().compareTo(idUsuario) == 0) {
                if (usuario.getEmail().compareTo("") != 0) {
                    //Crearemos una alerta para avisar al usuario con sus datos de acceso.
                    String mensaje = "A continuación le mostramos sus datos de usuario en AplicacionONGD.\n Su idUsuario es: " + usuario.getIdusuario()
                            + " y la contraseña es: " + usuario.getPassword() + ".";
                    List<String> direccion = new ArrayList<String>();
                    direccion.add(usuario.getEmail());
                    contSesion.getControladorConfiguracion().enviarAlerta(direccion, "Datos de Acceso", mensaje);
                }
                return true;
            }
        }
        return false;
    }

    /**
     * Método que envia emails a los usuarios con las cuotas.
     * @param cuotas Lista de Cuotas
     * @param cuotasPendientes Lista de cuotas pendientes
     * @return true si se ha realizado la operación
     */
    public boolean enviarEmailCuotasSinAlertas(List<Cuota> cuotas, List<Cuota> cuotasPendientes) {
        List<String> direcciones = new ArrayList<String>();
        direcciones = buscarEmailUsuariosActivos();
        Persona p;
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        //Si existen direcciones creamos el proyecto
        if (!direcciones.isEmpty()) {
            String mensaje = "Las siguientes cuotas van a llegar a su vencimiento:\n";
            for (Cuota c : cuotas) {
                mensaje += "\t- Dni de la persona: " + c.getPersona().getDni() + " Nombre: " + c.getPersona().getNombre()
                        + " Apellidos: " + c.getPersona().getApellidos() + " Fecha de pago: " + sdf.format(c.getFechaPago())
                        + " Cantidad: " + c.getCantidad() + "\n";
            }
            if (!cuotasPendientes.isEmpty()) {
                mensaje += "\n\n\n Otras cuotas pendientes anteriores son:\n";
                for (Cuota c : cuotasPendientes) {
                    mensaje += "\t- Dni de la persona: " + c.getPersona().getDni() + " Nombre: " + c.getPersona().getNombre()
                            + " Apellidos: " + c.getPersona().getApellidos() + " Fecha de pago: " + sdf.format(c.getFechaPago())
                            + " Cantidad: " + c.getCantidad() + "\n";
                }
            }
            contSesion.getControladorConfiguracion().enviarAlerta(direcciones, "Vencimiento de cuotas de este mes", mensaje);
            return true;
        }
        return false;

    }

    /**
     * Método que devuelve la lista de emails de usuarios activos que quieren recibir avisos.
     * @return lista de emails.
     */
    public List<String> buscarEmailUsuariosActivos() {
        List<String> direcciones = new ArrayList<String>();
        for (Usuario u : obtenerUsuariosActivos()) {
            //Si el usuario tiene email le amadimos a la lista.
            if (u.getEmail().compareTo("") != 0 && u.getAvisos()) {
                direcciones.add(u.getEmail());
            }
        }
        return direcciones;
    }

    /**
     * Método que devuelve la lista de usuarios activos.
     * @return lista de usuarios.
     */
    public List<Usuario> obtenerUsuariosActivos() {
        List<Usuario> usuarios = new ArrayList<Usuario>();
        for (Usuario usuario : obtenerUsuarios()) {
            if (usuario.getActivo()) {
                usuarios.add(usuario);
            }
        }
        return usuarios;
    }

    /**
     * Método que devuelve una lista de usuarios desactivados.
     * @return lista de usuarios desactivados.
     */
    public List<Usuario> obtenerUsuariosDesactivados() {
        List<Usuario> usuarios = new ArrayList<Usuario>();
        for (Usuario usuario : obtenerUsuarios()) {
            if (!usuario.getActivo()) {
                usuarios.add(usuario);
            }
        }
        return usuarios;
    }

    /**
     * Método que obtiene todos los usuarios de la base de datos.
     * @return lista de usuarios
     */
    public List<Usuario> obtenerUsuarios() {
        return (List<Usuario>) contP.obtenerEntidades(Usuario.class);
    }

    /**
     * Método que devuelve un objeto del tipo ControladorPersistencia.
     * @return contP
     * @see #setContP
     */
    public ControladorPersistencia getContP() {
        return contP;
    }

    /**
     * Método que establece un objeto del tipo ControladorPersistencia.
     * @param contP Nuevo valor de la variable
     * @see #getContP
     */
    public void setContP(ControladorPersistencia contP) {
        this.contP = contP;
    }

    /**
     * Método que devuelve un objeto del tipo ControladorSesion.
     * @return contSesion
     * @see #setContSesion
     */
    public ControladorSesion getContSesion() {
        return contSesion;
    }

    /**
     * Método que establece un objeto del tipo ControladorSesion.
     * @param contSesion Nuevo valor de la variable
     * @see #getContSesion
     */
    public void setContSesion(ControladorSesion contSesion) {
        this.contSesion = contSesion;
    }
}
